module cpu_top #(
    parameter IMEM_DEPTH = 256   // 指令存储深度（按字）
)(
    input  wire clk,   // 时钟：所有时序单元在上升沿工作
    input  wire rstn   // 同步复位（低有效）：拉低一个或多个时钟上升沿生效
);

    // =========================================================================
    // IF 取指阶段
    //   - pc 仅做：复位到 0，每拍 +4
    //   - imem 按字对齐读取指令（addr[31:2] 作为字地址）
    //   - if_id_reg 打拍 pc 与 instr，进入 ID 阶段
    // =========================================================================
    wire [31:0] pc_q;        // 当前取指地址（字节地址）
    wire [31:0] instr_if;    // 从指令存储取出的指令字

    pc u_pc(
        .clk (clk),
        .rstn(rstn),
        .pc_q(pc_q)
    );

    // 说明：imem 内部不做 $readmemh，便于 tb 层统一加载（层次路径：dut.u_imem.mem）
    imem #(
        .DEPTH_WORDS(IMEM_DEPTH)
    ) u_imem (
        .addr (pc_q),
        .instr(instr_if)
    );

    // IF/ID 级间寄存器：把 pc 与 instr 打拍给 ID
    wire [31:0] id_pc;
    wire [31:0] id_instr;
    if_id_reg u_ifid(
        .clk     (clk),
        .rstn    (rstn),
        .if_pc   (pc_q),
        .if_instr(instr_if),
        .id_pc   (id_pc),
        .id_instr(id_instr)
    );

    // =========================================================================
    // ID 译码/读寄存器阶段
    //   - controller：根据 opcode/funct3/funct7 组合译码出：regwrite / alusrc / alu_ctrl
    //   - regfile   ：组合读 rs1, rs2；同步写（x0 恒 0）
    //   - imm_gen   ：生成 I 型有符号扩展立即数
    //   - id_ex_reg ：将 rs1、rs2、imm 及控制信号打拍到 EX
    // =========================================================================
    // RISC-V 位段（供直连与注释理解；控制器内部也会拆解）
    wire [4:0] rs1 = id_instr[19:15];
    wire [4:0] rs2 = id_instr[24:20];
    wire [4:0] rd  = id_instr[11:7];

    // controller：当前仅输出三条信号
    wire        c_regwrite;  // 本指令最终是否需要写回寄存器堆
    wire        c_alusrc;    // 1=ALU 的 B 源取 imm（I 型），0=取 rs2（R 型）
    wire [3:0]  c_alu_ctrl;  // 0000=ADD，0001=SUB（与 alu.v 对齐）

    controller u_ctrl(
        .instr    (id_instr),
        .regwrite (c_regwrite),
        .alusrc   (c_alusrc),
        .alu_ctrl (c_alu_ctrl)
    );

    // 寄存器堆：组合读（rdata1/rdata2），同步写（在 WB 阶段完成）
    wire [31:0] rdata1;
    wire [31:0] rdata2;
    regfile u_rf(
        .clk   (clk),
        .rstn  (rstn),
        .we    (wb_regwrite),   // 来自 MEM/WB 的写回使能
        .rs1   (rs1),
        .rs2   (rs2),
        .rd    (wb_rd),         // 回写目的寄存器
        .wdata (wb_alu_y),      // 回写数据（最小版：恒为 ALU 结果）
        .rdata1(rdata1),
        .rdata2(rdata2)
    );

    // 立即数生成：仅 I 型用到（ADDI）
    wire [31:0] imm_i;
    imm_gen u_imm(
        .instr(id_instr),
        .imm_i(imm_i)
    );

    // ID/EX 级间寄存器：把 ID 阶段的数据与控制信号打拍给 EX
    wire [31:0] ex_rdata1;
    wire [31:0] ex_rdata2;
    wire [31:0] ex_imm;
    wire [4:0]  ex_rd;
    wire        ex_regwrite;
    wire        ex_alusrc;
    wire [3:0]  ex_alu_ctrl;

    id_ex_reg u_idex(
        .clk        (clk),
        .rstn       (rstn),
        .id_rdata1  (rdata1),
        .id_rdata2  (rdata2),
        .id_imm     (imm_i),
        .id_rd      (rd),
        .id_regwrite(c_regwrite),
        .id_alusrc  (c_alusrc),
        .id_alu_ctrl(c_alu_ctrl),
        .ex_rdata1  (ex_rdata1),
        .ex_rdata2  (ex_rdata2),
        .ex_imm     (ex_imm),
        .ex_rd      (ex_rd),
        .ex_regwrite(ex_regwrite),
        .ex_alusrc  (ex_alusrc),
        .ex_alu_ctrl(ex_alu_ctrl)
    );

    // =========================================================================
    // EX 执行阶段
    //   - 选择 ALU 的 B 源：I 型 -> imm；R 型 -> rs2
    //   - ALU 根据 alu_ctrl 执行加/减；结果进入 EX/MEM
    // =========================================================================
    wire [31:0] alu_b = ex_alusrc ? ex_imm : ex_rdata2; // B 源多路选择
    wire [31:0] alu_y;                                   // ALU 运算结果

    alu u_alu(
        .a        (ex_rdata1),
        .b        (alu_b),
        .alu_ctrl (ex_alu_ctrl),  // 0000=ADD, 0001=SUB
        .y        (alu_y)
    );

    // EX/MEM 级间寄存器：把 ALU 结果与写回元信息打拍给 MEM
    wire [31:0] mem_alu_y;
    wire [4:0]  mem_rd;
    wire        mem_regwrite;

    ex_mem_reg u_exmem(
        .clk        (clk),
        .rstn       (rstn),
        .ex_alu_y   (alu_y),
        .ex_rd      (ex_rd),
        .ex_regwrite(ex_regwrite),
        .mem_alu_y  (mem_alu_y),
        .mem_rd     (mem_rd),
        .mem_regwrite(mem_regwrite)
    );

    // =========================================================================
    // MEM 访存阶段（占位）
    //   - 本最小版本无访存操作；未来加入 LW/SW 时，此处连接 dmem，并在流水寄存器中
    //     传递 memread/memwrite/memtoreg 与写数据通路
    // =========================================================================

    // =========================================================================
    // WB 回写阶段
    //   - 本最小版本仅从 ALU 路径写回（无 memtoreg 选择器）
    //   - 将 wb_alu_y 写入 regfile[wb_rd]，受 wb_regwrite 控制
    // =========================================================================
    wire [31:0] wb_alu_y;
    wire [4:0]  wb_rd;
    wire        wb_regwrite;

    // MEM/WB 级间寄存器：把写回相关信息从 MEM 打拍到 WB
    mem_wb_reg u_memwb(
        .clk         (clk),
        .rstn        (rstn),
        .mem_alu_y   (mem_alu_y),
        .mem_rd      (mem_rd),
        .mem_regwrite(mem_regwrite),
        .wb_alu_y    (wb_alu_y),
        .wb_rd       (wb_rd),
        .wb_regwrite (wb_regwrite)
    );
endmodule